﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using System.Linq;

public class MouseInteraction : MonoBehaviour 
{
	public GameObject menuItem;
	public GameObject panel;
	public GameObject buffer;
	public GameObject player;
	public List<Transform> persistent;
	public Text mouseOverText;
	public RectTransform mouseXTransform;
	public Animator anim;


	private float menuItemHeight;
	private float menuTitleHeight;
	public float topBuffer;
	private RightClickOption cancel;
	private WalkHere walkHere;


	void Awake () 
	{	cancel = new RightClickOption () 
		{
			actionName = "Cancel",
			sortingOrder = GameConstants.Last,
			color = RightClickOption.XColor.none,
		};
		walkHere = new WalkHere () 
		{
			actionName = "Walk Here",
			sortingOrder = GameConstants.Last - 1,
			color = RightClickOption.XColor.yellow,
		};
		menuItemHeight = menuItem.GetComponent<RectTransform> ().rect.height;
	}
	
	void Update()
	{	

			List<RightClickOption> options;
			options = Cast ();
			if (options != null && options.Count > 0)
			{
				mouseOverText.text = options [0].actionName;

				if (Input.GetMouseButtonDown (0))
				{	
					
					X (options [0].color);

					GameObject currentSelectedObject = EventSystem.current.currentSelectedGameObject;
					if (currentSelectedObject == null || !currentSelectedObject.transform.IsChildOf (this.transform))
					{
					
						options [0].Action (player);
						ClearCanvas ();

						return;
					}

				}

			} else
			{
				mouseOverText.text = "";
			}
		if (Input.GetMouseButtonDown (1))
		{	ClearCanvas ();
			options = Cast ();
			MakeRightClickMenu (options);
		}

	}

	void ClearCanvas()
	{	
		foreach (Transform transform in this.transform)
		{	
			if (!persistent.Contains(transform))
			Destroy (transform.gameObject);
		}
	}

	List<RightClickOption> UIOptions()
	{	List<RightClickOption> sortedOptions = new List<RightClickOption> ();
		PointerEventData pointerData = new PointerEventData(EventSystem.current);
		pointerData.position = Input.mousePosition;
		List<RaycastResult> results = new List<RaycastResult>();
		EventSystem.current.RaycastAll (pointerData, results);
		if (results != null && results.Count > 0)
		{
			RightClickOption[] options;
			options = results [0].gameObject.GetComponents<RightClickOption> ();

			sortedOptions = SortOptionArray (options);
		}
		return sortedOptions;

	}

	List<RightClickOption> WorldOptions()
	{	List<RightClickOption> sortedOptions = new List<RightClickOption>();
		if (Camera.main != null)
		{	
			Ray ray;
			RaycastHit hit;

			ray = Camera.main.ScreenPointToRay (Input.mousePosition);
			RightClickOption[] options = new RightClickOption[0];
			if (Physics.Raycast (ray, out hit))
			{	
				
				walkHere.position = hit.point;
				options = hit.transform.gameObject.GetComponents<RightClickOption> ();
				sortedOptions = SortOptionArray (options);
				sortedOptions.Add (walkHere);
				sortedOptions.Add (cancel);
			}

		}
		return sortedOptions;
	}

	List<RightClickOption> Cast()
	{	List<RightClickOption> options;
		if (EventSystem.current.IsPointerOverGameObject ())
		{	
			options = UIOptions ();
		} else
		{	 
			options = WorldOptions ();
		}
		return options;
	}


	void MakeRightClickMenu(List<RightClickOption> options)
	{	
		ClearCanvas ();
		if (options != null && options.Count > 0)
		{	
			GameObject item = Instantiate (panel, this.transform);

			RectTransform rect = item.GetComponent<RectTransform> ();
			rect.transform.position = Input.mousePosition;
			rect.sizeDelta = new Vector2(rect.sizeDelta.x,menuItemHeight*options.Count+topBuffer);
			for (int i = 0; i < options.Count; i++)
			{	
				MenuItem (options [i], i);
			}

			GameObject bufferTemp = Instantiate (buffer, this.transform);
			RectTransform bufferRect = bufferTemp.GetComponent<RectTransform> ();
				bufferRect.transform.position = Input.mousePosition;
			bufferRect.sizeDelta = new Vector2(rect.sizeDelta.x,topBuffer);
		}

		
	}

	List<RightClickOption> SortOptionArray(RightClickOption[] option)
	{	
		List<RightClickOption> optionList = new List<RightClickOption> ();
		if (option.Length > 0)
		{
			optionList.AddRange (option);
			foreach (RightClickOption o in option)
			{
				if (!o.enabled)
				{
					optionList.Remove (o);
				}
						
			}
			optionList = optionList.OrderBy (obj => obj.sortingOrder).ToList ();
		}
		return optionList;
	}

	void MenuItem(RightClickOption option, int index)
	{	
		GameObject item = Instantiate (menuItem,this.transform);
		RectTransform rect = item.GetComponent<RectTransform> ();
		rect.transform.position = Input.mousePosition;
		rect.localPosition = new Vector2(rect.localPosition.x ,rect.localPosition.y - rect.rect.height * index-topBuffer);
		Text text = item.GetComponentInChildren<Text> ();
		Button button = item.GetComponent<Button> ();
		if (text != null && button != null)
		{
			text.text = option.actionName;
			button.onClick.AddListener (delegate{option.Action(player);});
			button.onClick.AddListener (ClearCanvas);
		}
	}
	void X(RightClickOption.XColor color)
	{
		mouseXTransform.position = Input.mousePosition;
		if (color == RightClickOption.XColor.red)
		{
			anim.Play ("RedX", -1, 0f);
		} else if (color == RightClickOption.XColor.yellow)
		{
			anim.Play ("YellowX", -1, 0f);
		}
	}
}
